#include "Array.hpp"

void Array::print(std::ostream& out)
{
    out << YELLOW <<"\n" ;
    for ( size_t l=0; l<width_; ++l)
        out << "======  " ;
    out << std::endl;
    for ( size_t i=(width_-1); i>0; --i)
    {
        for ( size_t j=0; j<width_; ++j)
            out << std::fixed <<std::setprecision(5) <<array_dyn[(i*width_+j)] << " ";
        out << "\n";
    }
    for ( size_t j=0; j<width_; ++j)
            out << std::fixed <<std::setprecision(5) <<array_dyn[j] << " ";
    out << WHITE <<"\n" ;
}

void Array::printGNUPLOT(std::ostream& out)
{
    out <<"# X\tY\tvalue\n";
    int sizeArray=width_*width_;
    int auxX=0;
        for(int i=0;i<sizeArray;++i)
        {
	    out <<auxX*h_<<"\t"<<(i-auxX*width_)*h_<<"\t"<<array_dyn[i]<<"\n";
            if((i+1)%width_==0)
            {
                ++auxX;
                out<<"\n";
            }
        }
}

void Array::print2(std::ostream& out)
{
    out <<"#[row,column]\tvalue\n";
    int sizeArray=width_*width_;
    int auxX=0;
        for(int i=0;i<sizeArray;++i)
        {
            out <<"["<<auxX<<","<<i-auxX*width_<<"]\t"<<array_dyn[i]<<"\n";
            if((i+1)%width_==0)
            {
                ++auxX;
                out<<"\n";
            }
        }
}

real Array::l2Norm() const
{
    real norm=0.0;
    for ( size_t q = 1; q <width_; ++q)
    {
        for ( size_t p = 1; p <width_; ++p)				
            norm +=(array_dyn[q*width_+p])*(array_dyn[q*width_+p])  ;
    }

    norm= sqrt(norm/(width_*width_));
    return norm;
}

real Array::infNorm() const
{
    size_t sizeArray=width_*width_;
    real max=array_dyn[0];
    for(size_t i=0;i<sizeArray;++i)
    {
        if(max<array_dyn[i])
            max=array_dyn[i];
    }
    return max;
}

void Array::fill(const real& in)
{ 
    for ( size_t n=0; n<width_*width_ ; ++n)
        array_dyn[n]=in;
}


void Array::setDirichletBoundary(std::function<real(real,real)> g, BOUNDARY bound)
{
    if(bound==NORTH)
    {
        for (size_t p = 0; p <width_; ++p)	
            array_dyn[(width_-1)*width_+p] = g((width_-1)*h_,p*h_);
    }
    else if(bound==SOUTH)
    {
        for (size_t p=0;p<width_;++p)	
            array_dyn[p] = g(0,p*h_);
    }
    else if(bound==WEST)
    {
        for (size_t q = 0; q<width_;++q)
            array_dyn[q*width_] = g(q*h_,0.0);
    }
    else 
    {
        for (size_t q=0;q<width_;++q)
            array_dyn[q*width_+(width_-1)] = g(q*h_,(width_-1)*h_);
    }
}

void Array::setAllDirichletBoundary(std::function<real(real,real)> g)
{
    for ( size_t q = 0; q <width_; ++q)
    {
        //west boundary
        array_dyn[q*width_] = g(q*h_,0.0);
        //east boundary
        array_dyn[q*width_+(width_-1)] = g(q*h_,(width_-1)*h_);
    }
    for ( size_t p = 0; p <width_; ++p)	
    {		
        //south boundary
        array_dyn[p] = g(0,p*h_);
        //north boundary
        array_dyn[(width_-1)*width_+p] = g((width_-1)*h_,p*h_);
    }
}
